package com.cskaoyan.javase.oop3._2inner._3local._2usecase;

/**
 * 局部内部类在开发中的实际用途,主要是结合:
 *      1.方法
 *      2.接口和抽象类
 * 具体来说就是:
 * 局部内部类经常使用在以下两个场景中：
 *
 *      1.方法需要返回一个对象，返回值类型是引用数据类型时。
 * 方法需要返回一个对象时，可以在方法的局部位置写一个 局部内部类 继承/实现外部的类/接口，创建对象后作为返回值。这是因为方法的返回值可以是返回值类型的对象，也可以是子类对象（当返回值类型是引用数据类型时）。
 *      2.方法需要传入一个对象，形参数据类型是引用数据类型时。
 * 方法需要传入一个对象实参时，可以在调用方法的位置定义一个 局部内部类 来继承/实现外部的类/接口，创建对象后作为方法的实参传入。这是因为方法的实参可以是形参类型的对象，也可以子类对象（当返回值类型是引用数据类型时）。
 *
 * 使用局部内部类的优点：
 *      1.绝对对外界隐藏，封装。
 *      2.相比较于传统的定义类，然后创建对象，它相对更加简洁省事。
 *          但是从类的定义的代码上来说,也没有简单多少
 *          所以它还有更进一步简化的可能性
 *          这就是后面马上要学习的匿名内部,Lambda表达式
 *          匿名内部,Lambda表达式都是特殊的局部内部类,它们的特点有很多和局部内部类相似的地方
 *
 * 缺点：
 *      这个类是一次性的。
 *
 * 综上，假如在局部位置需要一次性的使用某个对象，可以使用局部内部类创建它，但是如果多次在不同的方法中使用，使用局部内部类就得不偿失了。
 * 实际开发中,接口最常用局部内部类创建对象,抽象类基本没有.
 *
 * @since 11:04
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        method(new A());
        method(new ASon());
        class ASon extends A {
            @Override
            void test() {
                System.out.println("8888888888~");
            }
        }
        method(new ASon());
        class BaseASon extends BaseA{
            @Override
            public void testAbstract() {
                System.out.println("我是利用局部内部类,实现了抽象类BaseA的抽象方法");
            }
        }
        method(new BaseASon());
        // 该方法的返回值对象具体类型是不知道的,(IASon这个子类的作用范围仅在方法内部,这里访问不到)但它的父类类型是接口IA,所以可以用IA引用接收它,但这时不能访问该子类的独有成员
        IA a = method();
        a.testAbstract();
    }

    /*
        需求1:
            要求创建A的子类对象,重写test方法实现,重写为输出"7777~"
        常规做法是定义子类,重写方法
        实际上也可以在调用方法的位置,使用局部内部类
        这利用局部内部类继承一个外部类实现
     */
    public static void method(A a) {
        a.test();
    }

    public static void method(BaseA ba) {
        ba.testAbstract();
    }

    public static IA method() {
        class IASon implements IA{
            @Override
            public void testAbstract() {
                System.out.println("我是利用局部内部类,实现了接口IA的抽象方法");
            }
            // 接口的局部内部类实现类中的独有方法
            public void test(){}
        }
        return new IASon();
    }
}

abstract class BaseA {
    public abstract void testAbstract();
}

interface IA {
    void testAbstract();
}

class A {
    void test() {
        System.out.println("66666666~~");
    }
}

class ASon extends A {
    @Override
    void test() {
        System.out.println("7777777777777~");
    }
}
